package cn.ichiva.game.gobang;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @Description 五子棋
 * @auther Chiva 874460517@qq.com
 * @create 2020-01-08 14:41
 */
public class Gobang {

    /**
     * 白子
     */
    public static final boolean WHITE = false;
    /**
     * 黑子
     */
    public static final boolean BLACK = true;

    /**
     * 棋盘 x
     */
    public static final int xLen = 10;
    /**
     * 棋盘 y
     */
    public static final int yLen = 10;
    /**
     * 致胜点
     */
    private static final int WINNING_POINT = 5;

    /**
     * 棋盘
     */
    private Boolean[][] checkerboard = new Boolean[xLen][yLen];

    /**
     * 黑子执棋
     */
    private boolean flag = BLACK;
    /**
     * 总步数
     */
    private int index = 0;

    /**
     * 获取执棋方
     * @return
     */
    public boolean getFlag(){
        return flag;
    }

    /**
     * 下子
     * @param x
     * @param y
     * @param flag 黑子 = true,白子 = false,
     * @return
     */
    public boolean play(int x,int y,boolean flag){
        if(this.flag != flag){
            throw new RuntimeException("此处应该落:" + (this.flag?"黑子":"白子"));
        }

        if(null != checkerboard[x][y]){
            throw new RuntimeException("不能在此落子:(" + x + ',' + y +")");
        }

        checkerboard[x][y] = this.flag;
        boolean win = winnerCheck(x, y, this.flag);

        this.flag = !this.flag;
        this.index++;

        return win;
    }

    /**
     * x轴方向比较
     * @param x
     * @param y
     * @return
     */
    private boolean winnerCheckX(int x, int y, Boolean flag){
        int x1 = x + 1,x2 = x -1, index = 1;
        while (x1 < xLen && checkerboard[x1++][y] == flag) index++;
        while (x2 >= 0 && checkerboard[x2--][y] == flag) index++;
        return index >= WINNING_POINT;
    }

    /**
     * y轴方向比较
     * @param x
     * @param y
     * @param flag
     * @return
     */
    private boolean winnerCheckY(int x, int y, Boolean flag){
        int y1 = y + 1,y2 = y - 1, index = 1;
        while (y1 < yLen && checkerboard[x][y1++] == flag) index ++;
        while (y2 >= 0 && checkerboard[x][y2--] == flag) index ++;
        return index >= WINNING_POINT;
    }

    /**
     * xy轴方向比较
     * @param x
     * @param y
     * @param flag
     * @return
     */
    private boolean winnerCheckXY(int x, int y, Boolean flag){
        int x1 = x + 1,x2 = x -1,y1 = y + 1,y2 = y - 1, index = 1;
        while (x1 < xLen && y1 < yLen && checkerboard[x1++][y1++] == flag) index ++;
        while (x2 >= 0 && y2 >= 0 && checkerboard[x2--][y2--] == flag) index ++;
        return index >= WINNING_POINT;
    }

    /**
     * yx轴方向比较
     * @param x
     * @param y
     * @param flag
     * @return
     */
    private boolean winnerCheckYX(int x, int y, Boolean flag){
        int x1 = x + 1,x2 = x -1,y1 = y + 1,y2 = y - 1, index = 1;
        while (x1 < xLen && y2 >= 0 && checkerboard[x1++][y2--] == flag) index ++;
        while (x2 >= 0 && y1 < yLen && checkerboard[x2--][y1++] == flag) index ++;
        return index >= WINNING_POINT;
    }

    /**
     * 可以沿8个方向进行判定
     * @param x
     * @param y
     * @return
     */
    private boolean winnerCheck(int x, int y, Boolean flag) {
        if(winnerCheckX(x,y,flag)){
            return true;
        }else if(winnerCheckY(x,y,flag)){
            return true;
        }else if(winnerCheckXY(x,y,flag)){
            return true;
        }else if(winnerCheckYX(x,y,flag)){
            return true;
        }

        return false;
    }

    /**
     * x 轴边界检查
     * @param x
     * @return
     */
    private boolean corssCheckX(int x) {
        return x>=0 && x< xLen;
    }

    /**
     * y 轴边界检查
     * @param y
     * @return
     */
    private boolean corssCheckY(int y) {
        return y>=0 && y< yLen;
    }

    private SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss");

    @Override
    public String toString() {
        StringBuffer buffer = new StringBuffer("\t 步=\t").append(index).append("\n\r");
        for (int x = 0; x < xLen; x++) {
            buffer.append('\t').append(x);
        }

        for (int y = 0; y < yLen; y++) {
            buffer.append("\n\r").append(y).append("\t");
            for (int x = 0; x < xLen; x++) {
                if(null==checkerboard[x][y]) buffer.append('-');
                else if(checkerboard[x][y]) buffer.append('X');
                else buffer.append('O');

                buffer.append('\t');
            }
        }
        buffer.append("\n\r-----------------").append(format.format(new Date())).append("-----------------");

        return buffer.toString();
    }
}
